/**
 @file phy_drv_mars1s.c
 @copyright Copyright(C)  Centec Networks Inc.  All rights reserved.
 @date 2019-10-23
 @version v1.0
*/
#ifdef SUPPORT_PHY_MARS1S
#include "sal.h"
#include "phy_drv_common.h"
#include "phy_drv_api.h"
#include "phy_mars_common.h"

int32 ctc_phy_mars1s_set_phy_speed_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 value);
int32 ctc_phy_mars1s_set_phy_duplex_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 value);
int32 ctc_phy_mars1s_set_phy_speed_ability(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 value);
int32 ctc_phy_mars1s_get_phy_speed_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8* p_value);
int32 ctc_phy_mars1s_get_phy_duplex_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8* p_value);
int32 ctc_phy_mars1s_get_phy_speed_ability(uint8 lchip, ctc_chip_mdio_para_t* param, uint8* p_value);

extern phy_info_t g_phy_port_info[CTC_MAX_PHY_PORT_NUM];

/*****************************************************************************/
static int32
mars1s_get_page_val(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page,uint16* p_val)
{
    if(page == MARS_PAGE_UTP)
    {
       *p_val = 0x0;
    }
    else if(page == MARS_PAGE_SGMII)
    {
       *p_val = 0x2;
    }
    else if(page == MARS_PAGE_LDS)
    {
       *p_val = 0x0;
    }
    else
    {
       return CTC_E_INVALID_PARAM;
    }

    return CTC_E_NONE;
}

static int32 
mars1s_reg_read(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 reg, uint16* value)
{
    param->reg = reg;
    PHY_MARS_ERROR_RETURN(ctc_phy_mdio_read(lchip,CTC_CHIP_MDIO_GE,param));

    *value = param->value;
    return CTC_E_NONE;
}

static int32 
mars1s_reg_write(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 reg, uint16 value)
{
    param->reg = reg;
    param->value = value;
    PHY_MARS_ERROR_RETURN(ctc_phy_mdio_write(lchip,CTC_CHIP_MDIO_GE,param));

    return CTC_E_NONE;
}

static int32 
mars1s_reg_write_mask(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 reg, uint16 value, uint16 mask)
{
    uint16 val = 0;
    PHY_MARS_ERROR_RETURN(mars1s_reg_read(lchip,param,reg,&val));
    value = (value & mask) | (val & ~mask);
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,reg,value));

    return CTC_E_NONE;
}

static int32 
mars1s_ext_reg_read(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 reg, uint16* value)
{
    uint16 val = 0;

    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,MARS_EXT_REG_ADDR,reg));
    PHY_MARS_ERROR_RETURN(mars1s_reg_read(lchip,param,MARS_EXT_REG_DATA,&val));

    *value = val;
    return CTC_E_NONE;
}

static int32 
mars1s_ext_reg_write(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 reg, uint16 value)
{
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,MARS_EXT_REG_ADDR,reg));
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,MARS_EXT_REG_DATA,value));

    return CTC_E_NONE;
}

static int32 
mars1s_ext_reg_write_mask(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 reg, uint16 value, uint16 mask)
{
    uint16 val = 0;

    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,MARS_EXT_REG_ADDR,reg));
    PHY_MARS_ERROR_RETURN(mars1s_reg_read(lchip,param,MARS_EXT_REG_DATA,&val));
    value = (value & mask) | (val & ~mask);
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,MARS_EXT_REG_DATA,value));

    return CTC_E_NONE;
}

static 
int32 mars1s_mmd_read(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 mmdaddr, uint16 reg, uint16 *value)
{
    uint16 val = 0;

    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,0xd,mmdaddr));
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,0xe,reg));
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,0xd,0x4000|mmdaddr));
    PHY_MARS_ERROR_RETURN(mars1s_reg_read(lchip,param,0xe,&val));

    *value = val;
    return CTC_E_NONE;
}

static 
int32 mars1s_mmd_write_mask(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 mmdaddr, uint16 reg, uint16 value, uint16 mask)
{
    uint16 val = 0;

    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,0xd,mmdaddr));
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,0xe,reg));
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,0xd,0x4000|mmdaddr));
    PHY_MARS_ERROR_RETURN(mars1s_reg_read(lchip,param,0xe,&val));
    value = (value & mask) | (val & ~mask);
    PHY_MARS_ERROR_RETURN(mars1s_reg_write(lchip,param,0xe,value));

    return CTC_E_NONE;
}

static int32 mars1s_page_access(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page)
{
    uint16 page_value = 0;

    PHY_MARS_ERROR_RETURN(mars1s_get_page_val(lchip, param, page, &page_value));
    if(page == MARS_PAGE_LDS)
    {
        PHY_MARS_ERROR_RETURN(mars1s_ext_reg_write_mask(lchip, param, MARS_PAGE_REG, MARS_PAGE_UTP, MARS_PAGE_MASK));
        PHY_MARS_ERROR_RETURN(mars1s_ext_reg_write_mask(lchip, param, 0x100, 0x0, 0x2));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(mars1s_ext_reg_write_mask(lchip, param, MARS_PAGE_REG, MARS_PAGE_UTP, MARS_PAGE_MASK));
        PHY_MARS_ERROR_RETURN(mars1s_ext_reg_write_mask(lchip, param, 0x100, 0x2, 0x2));
        PHY_MARS_ERROR_RETURN(mars1s_ext_reg_write_mask(lchip, param, MARS_PAGE_REG, page_value, MARS_PAGE_MASK));
    }

    return CTC_E_NONE;
}

static int32 ctc_phy_mars1s_ext_read(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 reg, uint16 *value)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_ext_reg_read(lchip,param,reg,value));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 ctc_phy_mars1s_ext_write(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 reg, uint16 value)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_ext_reg_write(lchip,param,reg,value));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_ext_write_mask(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 reg, uint16 value, uint16 mask)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_ext_reg_write_mask(lchip,param, reg,value,mask));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_page_read(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page, uint16 reg, uint16* value)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,page));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_reg_read(lchip,param,reg,value));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_page_write(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page, uint16 reg, uint16 value)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,page));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_reg_write(lchip,param,reg,value));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_page_write_mask(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page, uint16 reg, uint16 value, uint16 mask)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,page));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_reg_write_mask(lchip, param, reg, value, mask));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_page_ext_read(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page, uint16 reg, uint16* value)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,page));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_ext_reg_read(lchip,param,reg,value));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_page_ext_write(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page, uint16 reg, uint16 value)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,page));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_ext_reg_write(lchip,param,reg,value));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_page_ext_write_mask(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 page, uint16 reg, uint16 value, uint16 mask)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,page));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_ext_reg_write_mask(lchip,param,reg,value,mask));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_mmd_read(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 mmdaddr, uint16 reg, uint16* value)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,MARS_PAGE_UTP));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_mmd_read(lchip, param, mmdaddr, reg, value));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

int32 
ctc_phy_mars1s_mmd_write_mask(uint8 lchip, ctc_chip_mdio_para_t* param, uint16 mmdaddr, uint16 reg, uint16 value, uint16 mask)
{
    uint8 port_id = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_SEM_TAKE;

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_page_access(lchip,param,MARS_PAGE_UTP));

    PHY_MARS_ERROR_RETURN_WITH_SEM_GIVE(mars1s_mmd_write_mask(lchip, param, mmdaddr, reg, value, mask));

    PHY_MARS_SEM_GIVE;

    return CTC_E_NONE;
}

static int32 mars1s_phy_conf_set(uint8 lchip, ctc_chip_mdio_para_t* param,uint8 speed, uint8 duplex)
{
    uint16 reg4=0,reg9=0,reg0_mask =0,val =0;
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    /* config Auto-Negotiation Advertisement */
    switch(speed)
    {
        case GLB_SPEED_1G:
            if(duplex == GLB_DUPLEX_FULL)
            {
                reg4 = 0x1c01;
                reg9 = 0x200;
            }
            else if(duplex == GLB_DUPLEX_HALF)
            {
                reg4 = 0x1c01;
                reg9 = 0x100;
            }
            else
            {
                reg4 = 0x1c01;
                reg9 = 0x300;
            }
            break;
        case GLB_SPEED_100M:
            if(duplex == GLB_DUPLEX_FULL)
            {
                reg4 = 0x1d01;
                reg9 = 0;
            }
            else if(duplex == GLB_DUPLEX_HALF)
            {
                reg4 = 0x1c81;
                reg9 = 0;
            }
            else
            {
                reg4 = 0x1d81;
                reg9 = 0;
            }
            break;
        case GLB_SPEED_10M:
            if(duplex == GLB_DUPLEX_FULL)
            {
                reg4 = 0x1c41;
                reg9 = 0;
            }
            else if(duplex == GLB_DUPLEX_HALF)
            {
                reg4 = 0x1c21;
                reg9 = 0;
            }
            else
            {
                reg4 = 0x1c61;
                reg9 = 0;
            }
            break;
        default:
            if(duplex == GLB_DUPLEX_FULL)
            {
                reg4 = 0x1d41;
                reg9 = 0x200;
            } 
            else if(duplex == GLB_DUPLEX_HALF)
            {
                reg4 = 0x1ca1;
                reg9 = 0x100;
            }
            else
            {
                reg4 = 0x1de1;
                reg9 = 0x300;
            }
            break;
    }
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_AN_ADVERTI_REG, reg4, 0x1de1));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_1G_BASET_CTL_REG, reg9, 0x300));

    reg0_mask = 0x2140;
    if (g_phy_port_info[port_id].auto_neg_en == 0) /* Force mode*/
    {
        reg0_mask = 0x3140;/* mask for Auto-Negotiation */
    }
    /* config manual speed with Auto-Negotiation mask */
    if((speed == GLB_SPEED_10M)&&((duplex == GLB_DUPLEX_FULL)||(duplex == GLB_DUPLEX_MAX)))
    {
        val = 0x0100;
    }
    else if((speed == GLB_SPEED_10M)&&(duplex == GLB_DUPLEX_HALF))
    {
        val = 0x0000;
    }
    else if((speed == GLB_SPEED_100M)&&((duplex == GLB_DUPLEX_FULL)||(duplex == GLB_DUPLEX_MAX)))
    {
        val = 0x2100;
    }
    else if((speed == GLB_SPEED_100M)&&(duplex == GLB_DUPLEX_HALF))
    {
        val = 0x2000;
    }
    else if((speed == GLB_SPEED_1G)&&((duplex == GLB_DUPLEX_FULL)||(duplex == GLB_DUPLEX_MAX)))
    {
        val = 0x0140;
    }
    else if((speed == GLB_SPEED_1G)&&(duplex == GLB_DUPLEX_HALF))
    {    
        val = 0x0040;
    }
    else /* default speed 1G duplex full */
    {
        val = 0x0140;
    }
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, val, reg0_mask));

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_speed_force(lchip, param, &g_phy_port_info[port_id].speed_force));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_duplex_force(lchip, param, &g_phy_port_info[port_id].duplex_force));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_speed_ability(lchip, param, &g_phy_port_info[port_id].speed_ability));

    if (g_phy_port_info[port_id].auto_neg_en == 0) /* Force mode*/
    {

        /*When config force mode, need to powerdown and powerup port to notify link parter.*/
        if(g_phy_port_info[port_id].enable)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0800, 0x0800));
            if(speed == GLB_SPEED_10M)
            {
                sal_udelay(1000000); 
            }
            else
            {
                sal_udelay(200000);
            }
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0000, 0x0800));
        }
    }
    else
    {
        /* restart Auto-Negotiation */
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x1200, 0x1200));
    }

    return CTC_E_NONE;
}

static uint16
mars1s_get_lds_result(uint8 lchip, ctc_chip_mdio_para_t* param,uint16* p_result)
{
    uint16 value = 0;
    uint16 result = 0;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_LDS, 0xb, &value));
    if(value & 0x1)
    {
        result = MARS_LDS_RESULT_2_PAIR_10M;
    }
    else if(value & 0x2)
    {
        result = MARS_LDS_RESULT_2_PAIR_100M;
    }
    else if(value & 0x4)
    {
        result = MARS_LDS_RESULT_1_PAIR_10M;
    }
    else if(value & 0x8)
    {
        result = MARS_LDS_RESULT_1_PAIR_100M;
    }
    else if(value & 0x20)
    {
        result = MARS_LDS_RESULT_4_PAIR_100M;
    }
    else
    {
        result = MARS_LDS_RESULT_DEFAULT;
    }
    *p_result = result;

    return CTC_E_NONE;
}

static uint16
mars1s_do_soft_reset(uint8 lchip, ctc_chip_mdio_para_t* param)
{
    uint8 port_id;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    if(g_phy_port_info[port_id].enable == GLB_ENABLE)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x8000, 0x8000));
    }

    return CTC_E_NONE;
}

static int32
mars1s_get_page_link_status(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 page, uint32* p_link_up, uint32* p_speed)
{
    uint32 speed = CTC_PORT_SPEED_MAX;
    uint16 val;
    uint8 linkup;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, page, 0x11, &val));
    linkup = (val & 0x400) ? GLB_LINK_UP : GLB_LINK_DOWN;

    /*if link down, need read again.*/
    if(linkup == GLB_LINK_DOWN)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, page, 0x11, &val));
        linkup = (val & 0x400) ? GLB_LINK_UP : GLB_LINK_DOWN;
    }

    if(val & 0x8000)
    {
        speed = CTC_PORT_SPEED_1G;
    }
    else if(val &0x4000)
    {
        speed = CTC_PORT_SPEED_100M;
    }
    else
    {
        speed = CTC_PORT_SPEED_10M;
    }

    *p_link_up = linkup;
    *p_speed = speed;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_init(uint8 lchip, ctc_chip_mdio_para_t* param)
{
    uint16 val = 0;
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    ctc_phy_common_probe_id(lchip,param,&g_phy_port_info[port_id].phy_id);
    g_phy_port_info[port_id].lchip = lchip;/* init */
    g_phy_port_info[port_id].bus = param->bus;
    g_phy_port_info[port_id].phy_addr = param->phy_addr;
    g_phy_port_info[port_id].mac_if = GLB_MAC_INTERFACE_SGMII;/* init */
    g_phy_port_info[port_id].mdium = GLB_PORT_TYPE_COPPER;/* init */
    g_phy_port_info[port_id].duplex = GLB_DUPLEX_MAX;/* init */
    g_phy_port_info[port_id].speed = phy_speed_glb2ctc(GLB_SPEED_MAX);/* init */
    g_phy_port_info[port_id].auto_neg_en = 1;/* init */
    g_phy_port_info[port_id].enable = 1;/* init */
    g_phy_port_info[port_id].sem_take = ctc_phy_sem_take;/* init */
    g_phy_port_info[port_id].sem_give = ctc_phy_sem_give;/* init */
    g_phy_port_info[port_id].speed_force = phy_speed_glb2ctc(GLB_SPEED_1G);/* init */
    g_phy_port_info[port_id].duplex_force = GLB_DUPLEX_FULL;/* init */
    g_phy_port_info[port_id].speed_ability = MARS_SPD_DEFAULT;/* init */

    /* do phy hardware reset per-chip before do phy port init */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param, 0xa0ff, &val));
    if (val == 0x5555)
    {
        PHY_DEBUG_PRINT("port %d hardware reset!\n",ctc_phy_common_get_gport(g_phy_port_info,param));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write_mask(lchip,param, 0xa0c0, 0x8000, 0x8000));
        sal_udelay(50000);
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write(lchip, param, 0xa0ff, 0xaaaa));
    }

    /* config whole chip UTP to SGMII mode */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write_mask(lchip, param,0xa001,0x3,0x0007));
    
    /* enable interrupt */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write(lchip, param,0xa010,0xffff));
    /* clear interrupt status */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param,0xa011,&val));

    /* enable interrupt */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x12, 0x7800));
    /* clear interrupt status */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x13, &val));

    /* disable sleep mode */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x27, 0x0000, 0x8000));

    /* do phy software reset when do phy port init */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x8000, 0x8000));
    
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_deinit(uint8 lchip, ctc_chip_mdio_para_t* param)
{
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_link_up_status(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_link_up)
{
    uint16 val;
    uint8 linkup;

    /* read copper status */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x11, &val));
    linkup = (val & 0x400) ? GLB_LINK_UP : GLB_LINK_DOWN;

    /*if link down, need read again.*/
    if(linkup == GLB_LINK_DOWN)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x11, &val));
        linkup = (val & 0x400) ? GLB_LINK_UP : GLB_LINK_DOWN;
    }
    *p_link_up = linkup;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_port_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_DEBUG_PRINT("phy set port enable:%d \n", enable);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0000, 0x0800));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0800, 0x0800));
    }
    g_phy_port_info[port_id].enable = enable;
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_port_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val = 0;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, &val));
    PHY_DEBUG_PRINT("phy get port enable val:0x%x \n", val);

    *p_enable =((val>>11)&0x1)?0:1;
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_port_duplex(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 duplex)
{
    uint8 port_id;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    PHY_DEBUG_PRINT("phy set port duplex:%d \n", duplex);
    PHY_MARS_ERROR_RETURN(mars1s_phy_conf_set(lchip, param, phy_speed_ctc2glb(g_phy_port_info[port_id].speed), duplex));

    g_phy_port_info[port_id].duplex = duplex;
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_port_duplex(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_duplex)
{
    uint16 val;
    uint32 duplex, linkup;
    uint8 port_id = 0;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_link_up_status(lchip,param,&linkup));
    if(!linkup)
    {
        if(g_phy_port_info[port_id].duplex == GLB_DUPLEX_MAX)
        {
            *p_duplex = GLB_DUPLEX_FULL;
        }
        else
        {
            *p_duplex = g_phy_port_info[port_id].duplex;
        }
        return CTC_E_NONE;
    }

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x11, &val));
    PHY_DEBUG_PRINT("phy get port duplex reg 0x%x val:0x%x \n", 0x11, val);

    duplex = (val & 0x2000) ? GLB_DUPLEX_FULL : GLB_DUPLEX_HALF;
    *p_duplex = duplex;
    return CTC_E_NONE;
}

static int32
ctc_phy_mars1s_check_speed(uint32 speed)
{
    if((speed > CTC_PORT_SPEED_10M) && (speed != CTC_PORT_SPEED_MAX))
    {
        return ctc_phy_common_unsupport();
    }
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_port_speed(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 value)
{
    uint8 port_id;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    PHY_DEBUG_PRINT("phy set port speed:%d \n", value);
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_check_speed(value));
    PHY_MARS_ERROR_RETURN(mars1s_phy_conf_set(lchip, param, phy_speed_ctc2glb(value), g_phy_port_info[port_id].duplex));

    g_phy_port_info[port_id].speed = value;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_port_speed(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_value)
{
    uint32 speed = CTC_PORT_SPEED_MAX, linkup;
    uint16 value;
    uint16 result = 0;
    uint8 port_id = 0;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_link_up_status(lchip,param,&linkup));
    if(!linkup)
    {
        if(g_phy_port_info[port_id].speed == CTC_PORT_SPEED_MAX)
        {
            *p_value = CTC_PORT_SPEED_1G;
        }
        else
        {
            *p_value = g_phy_port_info[port_id].speed;
        }
        return CTC_E_NONE;
    }

    PHY_MARS_ERROR_RETURN(mars1s_get_lds_result(lchip,param,&result));
    if(result)
    {
        PHY_DEBUG_PRINT("phy get port lds result:0x%x \n", result);
        if(result == MARS_LDS_RESULT_2_PAIR_10M || result == MARS_LDS_RESULT_1_PAIR_10M)
        {
            speed = CTC_PORT_SPEED_10M;
        }
        else
        {
            speed = CTC_PORT_SPEED_100M;
        }
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x11, &value));
        PHY_DEBUG_PRINT("phy get port speed value:0x%x \n", value);

        if(value & 0x8000)
        {
            speed = CTC_PORT_SPEED_1G;
        }
        else if(value &0x4000)
        {
            speed = CTC_PORT_SPEED_100M;
        }
        else
        {
            speed = CTC_PORT_SPEED_10M;
        }
    }
    *p_value = speed; 
    return CTC_E_NONE;
}

static uint16
mars1s_port_status_sync(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    uint16 val0,val4,val9;
    uint8 port_id;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP,0x4,&val4));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP,0x9,&val9));
        PHY_DEBUG_PRINT("enable, phy get port auto speed value4:0x%x value9:0x%x \n", val4, val9);
        if(((val4 & 0x1e0) == 0x1e0) && (val9 & 0x200))
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_MAX & GLB_DUPLEX_MAX \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_MAX;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_MAX;
        }
        else if(((val4 & 0x1e0) == 0x140) && (val9 & 0x200))
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_MAX & GLB_DUPLEX_MAX \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_MAX;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_FULL;
        }
        else if((val4 & 0x1e0) == 0xa0)
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_MAX & GLB_DUPLEX_MAX \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_MAX;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_HALF;
        }
        else
        {
            if(val9 & 0x200)
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_1G & GLB_DUPLEX_FULL \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_1G;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_FULL;
            }
            else if((val4 & 0x180) == 0x180)
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_100M & GLB_DUPLEX_FULL \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_100M;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_MAX;
            }
            else if((val4 & 0x180) == 0x100)
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_100M & GLB_DUPLEX_FULL \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_100M;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_FULL;
            }
            else if((val4 & 0x180) == 0x80)
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_100M & GLB_DUPLEX_HALF \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_100M;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_HALF;
            }
            else if((val4 & 0x60) == 0x60)
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_10M & GLB_DUPLEX_FULL \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_10M;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_MAX;
            }
            else if((val4 & 0x60) == 0x40)
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_10M & GLB_DUPLEX_FULL \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_10M;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_FULL;
            }
            else if((val4 & 0x60) == 0x20)
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_10M & GLB_DUPLEX_HALF \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_10M;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_HALF;
            }
            else
            {
                PHY_DEBUG_PRINT("CTC_PORT_SPEED_10M & GLB_DUPLEX_HALF \n");
                g_phy_port_info[port_id].speed = CTC_PORT_SPEED_10M;
                g_phy_port_info[port_id].duplex= GLB_DUPLEX_HALF;
            }
        }
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP,0x0,&val0));
        PHY_DEBUG_PRINT("disable, phy get port speed value:0x%x \n", val0);

        if((val0 & 0x2140) == 0x140)
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_1G & GLB_DUPLEX_FULL \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_1G;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_FULL;
        }
        else if((val0 & 0x2140) == 0x40)
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_1G & GLB_DUPLEX_HALF \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_1G;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_HALF;
        }
        else if((val0 & 0x2140) == 0x2100)
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_100M & GLB_DUPLEX_FULL \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_100M;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_FULL;
        }
        else if((val0 & 0x2140) == 0x2000)
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_100M & GLB_DUPLEX_HALF \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_100M;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_HALF;
        }
        else if((val0 & 0x2140) == 0x100)
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_10M & GLB_DUPLEX_FULL \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_10M;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_FULL;
        }
        else if((val0 & 0x2140) == 0x0)
        {
            PHY_DEBUG_PRINT("CTC_PORT_SPEED_10M & GLB_DUPLEX_HALF \n");
            g_phy_port_info[port_id].speed = CTC_PORT_SPEED_10M;
            g_phy_port_info[port_id].duplex= GLB_DUPLEX_HALF;
        }
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_port_auto_neg_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);    
    PHY_DEBUG_PRINT("phy set port auto_neg:%d \n", enable);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x1000, 0x1000));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0000, 0x1000));
    }
    PHY_MARS_ERROR_RETURN(mars1s_port_status_sync(lchip, param, enable));
    g_phy_port_info[port_id].auto_neg_en = enable;
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_port_auto_neg_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, &val));
    PHY_DEBUG_PRINT("phy get port auto_neg value:0x%x \n", val);

    *p_enable = (val >> 12) & 0x1;
    return CTC_E_NONE;
}

static int32
mars1s_config_recover(uint8 lchip, ctc_chip_mdio_para_t* param)
{
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_port_en(lchip, param,g_phy_port_info[port_id].enable));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_port_auto_neg_en(lchip, param,g_phy_port_info[port_id].auto_neg_en));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_phy_speed_force(lchip,param, g_phy_port_info[port_id].speed_force));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_phy_duplex_force(lchip,param, g_phy_port_info[port_id].duplex_force));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_phy_speed_ability(lchip,param, g_phy_port_info[port_id].speed_ability));

    return CTC_E_NONE;
}

static int32 mars1s_config_loopback(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 lb_mode)
{
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);    

    switch (lb_mode)
    {
    case GLB_LB_NONE:
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0000, 0x4000)); /* disable internal loopback */
        PHY_MARS_ERROR_RETURN(mars1s_config_recover(lchip,param));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param, MARS_PAGE_UTP,0xa006,0x00,0x20)); /* disable external loopback */
        break;
    case GLB_LB_PHY_FAR:/* external loopback */
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0000, 0x4000)); /* disable internal loopback */
        PHY_MARS_ERROR_RETURN(mars1s_config_recover(lchip,param));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param, MARS_PAGE_UTP,0xa006,0x20,0x20)); /* enable external loopback */
        break;
    case GLB_LB_PHY_NEAR: /* internal loopback */
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param, MARS_PAGE_UTP,0xa006,0x00,0x20)); /* disable external loopback */
        if (g_phy_port_info[port_id].speed == CTC_PORT_SPEED_1G)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x4140, 0x7140)); /* force speed and enable internal loopback */
        }
        else if (g_phy_port_info[port_id].speed == CTC_PORT_SPEED_100M)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x6100, 0x7140)); /* force speed and enable internal loopback */
        }
        else if (g_phy_port_info[port_id].speed == CTC_PORT_SPEED_10M)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x4100, 0x7140)); /* force speed and enable internal loopback */
        }
        else /* default speed 1G */
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x4140, 0x7140)); /* force speed and enable internal loopback */
        }
        break;
    default:
        return RESULT_ERROR;
        break;
    }
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_linkup_event(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* user_data)
{
    uint16 val = 0;

    /* clear interrupt status */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param,0xa011,&val));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x13, &val));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_linkdown_event(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* user_data)
{
    uint16 val = 0;
    /* clear interrupt status */
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param,0xa011,&val));    
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x13, &val));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_port_loopback(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 mode)
{
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);    
    PHY_DEBUG_PRINT("phy set port loopback mode:%d \n", mode);
    PHY_MARS_ERROR_RETURN(mars1s_config_loopback(lchip, param,mode));

    g_phy_port_info[port_id].loopback_mode = mode;
    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_port_loopback(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* mode)
{
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);    
    *mode = g_phy_port_info[port_id].loopback_mode;
    return RESULT_OK;
}

int32
ctc_phy_mars1s_set_port_unidir_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 type)
{
    return ctc_phy_common_unsupport();
}

int32
ctc_phy_mars1s_get_port_unidir_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* type)
{
    *type = 0;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_port_medium(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 type)
{
    return ctc_phy_common_unsupport();
}

int32
ctc_phy_mars1s_get_port_medium(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* type)
{
    *type = GLB_PORT_TYPE_COPPER;
    return RESULT_OK;
}

static int32 
mars1s_set_phy_speed_force(uint8 lchip, ctc_chip_mdio_para_t* param,uint8 speed, uint8 duplex)
{
    uint16 val=0;
    uint8 port_id;
    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);

    /* config manual speed with Auto-Negotiation mask */
    if((speed == GLB_SPEED_10M)&&((duplex == GLB_DUPLEX_FULL)||(duplex == GLB_DUPLEX_MAX)))
    {
        val = 0x0100;
    }
    else if((speed == GLB_SPEED_10M)&&(duplex == GLB_DUPLEX_HALF))
    {
        val = 0x0000;
    }
    else if((speed == GLB_SPEED_100M)&&((duplex == GLB_DUPLEX_FULL)||(duplex == GLB_DUPLEX_MAX)))
    {
        val = 0x2100;
    }
    else if((speed == GLB_SPEED_100M)&&(duplex == GLB_DUPLEX_HALF))
    {
        val = 0x2000;
    }
    else if((speed == GLB_SPEED_1G)&&((duplex == GLB_DUPLEX_FULL)||(duplex == GLB_DUPLEX_MAX)))
    {
        val = 0x0140;
    }
    else if((speed == GLB_SPEED_1G)&&(duplex == GLB_DUPLEX_HALF))
    {    
        val = 0x0040;
    }
    else /* default speed 1G duplex full */
    {
        val = 0x0140;
    }
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, val, 0x2140));

    if (g_phy_port_info[port_id].auto_neg_en == 0) /* Force mode*/
    {
        /*When config force mode, need to powerdown and powerup port to notify link parter.*/
        if(g_phy_port_info[port_id].enable)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0800, 0x0800));
            if(speed == GLB_SPEED_10M)
            {
                sal_udelay(1000000); 
            }
            else
            {
                sal_udelay(200000);
            }
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, PHY_CTL_REG, 0x0000, 0x0800));
        }
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_phy_speed_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 value)
{
    uint8 port_id;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    PHY_DEBUG_PRINT("phy set port speed force:%d \n", value);
    PHY_MARS_ERROR_RETURN(mars1s_set_phy_speed_force(lchip, param, phy_speed_ctc2glb(value), g_phy_port_info[port_id].duplex_force));
    PHY_MARS_ERROR_RETURN(mars1s_port_status_sync(lchip, param, g_phy_port_info[port_id].auto_neg_en));

    g_phy_port_info[port_id].speed_force = value;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_phy_speed_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8* p_value)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP,0x0,&val));
    PHY_DEBUG_PRINT("phy get speed force value:0x%x \n", val);

    if((val & 0x2040) == 0x40)
    {
        PHY_DEBUG_PRINT("speed_force CTC_PORT_SPEED_1G \n");
        *p_value = CTC_PORT_SPEED_1G;
    }
    else if((val & 0x2040) == 0x2000)
    {
        PHY_DEBUG_PRINT("speed_force CTC_PORT_SPEED_100M \n");
        *p_value = CTC_PORT_SPEED_100M;
    }
    else
    {
        PHY_DEBUG_PRINT("speed_force CTC_PORT_SPEED_10M \n");
        *p_value = CTC_PORT_SPEED_10M;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_phy_duplex_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 value)
{
    uint8 port_id;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    PHY_DEBUG_PRINT("phy set port duplex_force:%d \n", value);
    PHY_MARS_ERROR_RETURN(mars1s_set_phy_speed_force(lchip, param, phy_speed_ctc2glb(g_phy_port_info[port_id].speed_force), value));
    PHY_MARS_ERROR_RETURN(mars1s_port_status_sync(lchip, param, g_phy_port_info[port_id].auto_neg_en));

    g_phy_port_info[port_id].duplex_force = value;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_phy_duplex_force(uint8 lchip, ctc_chip_mdio_para_t* param, uint8* p_value)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP,0x0,&val));
    PHY_DEBUG_PRINT("phy get duplex force value:0x%x \n", val);

    if(val & 0x100)
    {
        PHY_DEBUG_PRINT("speed_force GLB_DUPLEX_FULL \n");
        *p_value = GLB_DUPLEX_FULL;
    }
    else
    {
        PHY_DEBUG_PRINT("speed_force GLB_DUPLEX_HALF \n");
        *p_value = GLB_DUPLEX_HALF;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_phy_speed_ability(uint8 lchip, ctc_chip_mdio_para_t* param, uint8 ability)
{
    uint8 port_id;
    uint16 val = 0;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    PHY_DEBUG_PRINT("phy set port speed ab:0x%x \n", ability);
    if(ability & MARS_SPD_1000M_FULL)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x9, 0x200, 0x200));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x9, 0x000, 0x200));
    }
    if(ability & MARS_SPD_1000M_HALF)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x9, 0x100, 0x100));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x9, 0x000, 0x100));
    }

    if(ability & MARS_SPD_100M_FULL)
    {
        val |= 0x100;
    }
    else
    {
        val &= 0xfeff;
    }
    if(ability & MARS_SPD_100M_HALF)
    {
        val |= 0x80;
    }
    else
    {
        val &= 0xff7f;
    }
    if(ability & MARS_SPD_10M_FULL)
    {
        val |= 0x40;
    }
    else
    {
        val &= 0xffbf;
    }
    if(ability & MARS_SPD_10M_HALF)
    {
        val |= 0x20;
    }
    else
    {
        val &= 0xffdf;
    }
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x4, val, 0x1e0));

    if (g_phy_port_info[port_id].auto_neg_en)
    {
        /* restart Auto-Negotiation */
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x1200, 0x1200));
    }
    g_phy_port_info[port_id].speed_ability = ability;
    PHY_MARS_ERROR_RETURN(mars1s_port_status_sync(lchip, param, g_phy_port_info[port_id].auto_neg_en));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_phy_speed_ability(uint8 lchip, ctc_chip_mdio_para_t* param, uint8* p_value)
{
    uint16 val = 0;
    uint32 ability = 0;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x9, &val));
    PHY_DEBUG_PRINT("phy get port speed ab 04h:0x%x\n", val);
    if(val & 0x200)
    {
        ability |= MARS_SPD_1000M_FULL;
    }
    if(val & 0x100)
    {
        ability |= MARS_SPD_1000M_HALF;
    }

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x4, &val));
    PHY_DEBUG_PRINT("phy get port speed ab 09h:0x%x\n", val);
    if(val & 0x100)
    {
        ability |= MARS_SPD_100M_FULL;
    }
    if(val & 0x80)
    {
        ability |= MARS_SPD_100M_HALF;
    }
    if(val & 0x40)
    {
        ability |= MARS_SPD_10M_FULL;
    }
    if(val & 0x20)
    {
        ability |= MARS_SPD_10M_HALF;
    }

    *p_value = ability;

    return CTC_E_NONE;
}

static int32
mars1s_get_pkt_side(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_side)
{
    uint32 mask = 0x8000;
    uint16 val = 0;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0xa0, &val));
    PHY_DEBUG_PRINT("phy get port packet checker side valu:0x%x \n", val);
    if(val & mask)
    {
        *p_side = MARS_PACKET_CHECKER_DOWNSTREAM;
        return CTC_E_NONE;
    }
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_SGMII, 0x1a0, &val));
    PHY_DEBUG_PRINT("phy get port packet checker side vals:0x%x \n", val);
    if(val & mask)
    {
        *p_side = MARS_PACKET_CHECKER_UPSTREAM;
        return CTC_E_NONE;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_packet_checker(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable, uint32 side)
{
    uint16 regaddr = 0;
    uint16 unregaddr = 0;
    uint8 page = 0;
    uint8 unpage = 0;

    PHY_DEBUG_PRINT("phy set port packet_checker en:%d,side:%d \n", enable, side);

    if(side == MARS_PACKET_CHECKER_UPSTREAM)
    {
        regaddr = 0x1a0;
        unregaddr = 0xa0;
        page = MARS_PAGE_SGMII;
        unpage = MARS_PAGE_UTP;
    }
    else if(side == MARS_PACKET_CHECKER_DOWNSTREAM)
    {
        regaddr = 0xa0;
        unregaddr = 0x1a0;
        page = MARS_PAGE_UTP;
        unpage = MARS_PAGE_SGMII;
    }
    else
    {
        return ctc_phy_common_unsupport();
    }

    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x8000,0xc000));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,unpage,unregaddr,0x4000,0xc000));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x4000,0xc000));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,unpage,unregaddr,0x4000,0xc000));
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_packet_checker(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable, uint32* p_side)
{
    uint16 regaddr = 0;
    uint16 val = 0;
    uint8 page = 0;
    uint32 side = MARS_PACKET_CHECKER_STREAM_MAX;

    mars1s_get_pkt_side(lchip, param, &side);
    PHY_DEBUG_PRINT("phy get port packet checker en side:0x%x \n", side);
    if(side == MARS_PACKET_CHECKER_UPSTREAM)
    {
        page = MARS_PAGE_SGMII;
        regaddr = 0x1a0;
    }
    else if(side == MARS_PACKET_CHECKER_DOWNSTREAM)
    {
        page = MARS_PAGE_UTP;
        regaddr = 0xa0;
    }
    else
    {
        *p_side = side;
        *p_enable = GLB_DISABLE;
        return CTC_E_NONE;
    }

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr,&val));
    PHY_DEBUG_PRINT("phy get port packet_checker en val:0x%x \n", val);

    if((val & 0xc000) == 0x8000)
    {
        *p_enable = GLB_ENABLE;
    }
    else
    {
        *p_enable = GLB_DISABLE;
    }

    *p_side = side;
    PHY_DEBUG_PRINT("phy get port packet_checker side:%x \n", side);

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_packet_count(uint8 lchip, ctc_chip_mdio_para_t* param, void* p_pkt_count)
{
    uint16 regaddr = 0;
    uint16 regoff = 0;
    uint8 page = 0;
    uint16 good_high,good_low,errorcount;
    mars_packet_generator_count_t* packet_count = NULL;
    uint32 side = MARS_PACKET_CHECKER_STREAM_MAX;

    mars1s_get_pkt_side(lchip, param, &side);
    PHY_DEBUG_PRINT("phy get port packet checker en side:0x%x \n", side);
    packet_count = (mars_packet_generator_count_t*)p_pkt_count;
    if(side == MARS_PACKET_CHECKER_UPSTREAM)
    {
        page = MARS_PAGE_SGMII;
        regoff = 0x100;
    }
    else
    {
        page = MARS_PAGE_UTP;
        regoff = 0x0;
    }

    packet_count->side= side;

    regaddr = 0xa3;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr|regoff,&good_high));
    PHY_DEBUG_PRINT("phy get port packet count rx good_high:0x%x \n", good_high);
    regaddr = 0xa4;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr|regoff,&good_low));
    PHY_DEBUG_PRINT("phy get port packet count rx good_low:0x%x \n", good_low);
    packet_count->rx_good = (good_high << 16) | good_low;

    regaddr = 0xa9;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr|regoff,&errorcount));
    PHY_DEBUG_PRINT("phy get port packet count error:0x%x \n", errorcount);
    packet_count->rx_error = errorcount;

    regaddr = 0xad;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr|regoff,&good_high));
    PHY_DEBUG_PRINT("phy get port packet count tx good_high:0x%x \n", good_high);
    regaddr = 0xae;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr|regoff,&good_low));
    PHY_DEBUG_PRINT("phy get port packet count tx good_low:0x%x \n", good_low);
    packet_count->tx_good = (good_high << 16) | good_low;

    regaddr = 0xb3;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr|regoff,&errorcount));
    PHY_DEBUG_PRINT("phy get port packet count error:0x%x \n", errorcount);
    packet_count->tx_error = errorcount;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_packet_gen(uint8 lchip, ctc_chip_mdio_para_t* param, void* pv_arg)
{
    uint16 regaddr = 0;
    uint8 page = 0;
    mars_packet_generator_t* packet_gen;

    packet_gen = (mars_packet_generator_t*)pv_arg;
    PHY_DEBUG_PRINT("phy set port packet_gen num:%d,len:%d,addren:%d,sa:%d,da:%d \n", packet_gen->packet_num, \
        packet_gen->packet_len, packet_gen->addr_en, packet_gen->addr_sa, packet_gen->addr_da);

    regaddr = 0xa2;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,packet_gen->packet_num,0xffff));

    if((packet_gen->packet_len >= 64) && (packet_gen->packet_len <= 1512))
    {
        regaddr = 0xa1;
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip,param,page,regaddr,packet_gen->packet_len));
    }
    else
    {
        return ctc_phy_common_unsupport();
    }

    regaddr = 0x38;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,(packet_gen->addr_en & 0x1) << 12,0x1000));
    regaddr = 0x3a;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,packet_gen->addr_sa,0x00ff));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,(packet_gen->addr_da << 8),0xff00));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_packet_gen(uint8 lchip, ctc_chip_mdio_para_t* param, void* pv_arg)
{
    uint16 val;
    uint16 regaddr = 0;
    uint8 page = 0;
    mars_packet_generator_t* packet_gen;

    packet_gen = (mars_packet_generator_t*)pv_arg;

    regaddr = 0xa2;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr,&val));
    PHY_DEBUG_PRINT("phy get port packet gen num val:0x%x \n", val);
    packet_gen->packet_num = val;

    regaddr = 0xa1;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr,&val));
    PHY_DEBUG_PRINT("phy get port packet gen len val:0x%x \n", val);
    packet_gen->packet_len = val;

    regaddr = 0x38;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr,&val));
    PHY_DEBUG_PRINT("phy get port packet gen addr val:0x%x \n", val);
    if((val >> 12) & 0x1)
    {
        packet_gen->addr_en= GLB_ENABLE;
    }
    else
    {
        packet_gen->addr_en= GLB_DISABLE;
    }
    regaddr = 0x3a;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr,&val));
    PHY_DEBUG_PRINT("phy get port packet gen da sa val:0x%x \n", val);
    packet_gen->addr_sa = val & 0xff;
    packet_gen->addr_da = (val >> 8) & 0xff;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_packet_gen_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    uint16 val = 0;
    uint16 regaddr = 0;
    uint16 page = 0;

    PHY_DEBUG_PRINT("phy set port packet_gen enable:%d \n", enable);

    if(enable)
    {
        regaddr = 0xa0;
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x0000,0x6000));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x1000,0x1000));
    }
    else
    {
        regaddr = 0xa0;
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr,&val));
        if(val & 0x8000)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x0000,0x1000));
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x2000,0x7000));
        }
        else
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x0000,0x1000));
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip,param,page,regaddr,0x6000,0x7000));
        }
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_packet_gen_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val;
    uint16 regaddr = 0;
    uint16 page = 0;

    regaddr = 0xa0;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,regaddr,&val));
    PHY_DEBUG_PRINT("phy get port packet gen en val:0x%x \n", val);

    if((val >> 12) & 0x1)
    {
        *p_enable = GLB_ENABLE;
    }
    else
    {
        *p_enable = GLB_DISABLE;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_sleep_mode_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    PHY_DEBUG_PRINT("phy set port sleep_mode enable:%d \n", enable);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x27, 0x8000, 0x8000));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x27, 0x0000, 0x8000));
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_sleep_mode_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x27,&val));
    PHY_DEBUG_PRINT("phy get port sleep_mode val:0x%x \n", val);

    *p_enable = (val & 0x8000) ? GLB_ENABLE : GLB_DISABLE;

    return CTC_E_NONE;
}

static int32
mars1s_eee_patch(uint8 lchip, ctc_chip_mdio_para_t* param)
{
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip, param, MARS_PAGE_UTP, 0x1d, 0x318));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip, param, MARS_PAGE_UTP, 0x35, 0x622));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip, param, MARS_PAGE_UTP, 0x3c, 0x177));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip, param, MARS_PAGE_UTP, 0x78, 0x181f));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip, param, MARS_PAGE_UTP, 0x9d, 0x5));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_eee_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    PHY_DEBUG_PRINT("phy set port eee enable:%d \n", enable);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(mars1s_eee_patch(lchip, param));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_mmd_write_mask(lchip, param, 0x7, 0x3c, 0x6, 0x6));
        PHY_MARS_ERROR_RETURN(mars1s_do_soft_reset(lchip, param));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x9a, 0x0000, 0x8000));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_mmd_write_mask(lchip, param, 0x7, 0x3c, 0x0, 0x6));
        PHY_MARS_ERROR_RETURN(mars1s_do_soft_reset(lchip, param));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x9a, 0x8000, 0x8000));
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_eee_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_mmd_read(lchip, param, 0x7, 0x3c, &val));
    PHY_DEBUG_PRINT("phy get port eee val:0x%x \n", val);

    *p_enable = (val & 0x6) ? GLB_ENABLE : GLB_DISABLE;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_eee_status(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_status)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_mmd_read(lchip, param, 0x3, 0x1, &val));
    PHY_DEBUG_PRINT("phy get port eee_status val:0x%x \n", val);

    *p_status = ((val & 0x300) == 0x300) ? MARS_EEE : MARS_OUT_EEE;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_vct_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    PHY_DEBUG_PRINT("phy set port vct enable:%d \n", enable);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip, param, MARS_PAGE_UTP, 0x98, 0xb0a6));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_sleep_mode_en(lchip, param, GLB_DISABLE));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x80, 0x1,0x1));
    }

    return CTC_E_NONE;
}

static int32
mars1s_vct_status_prase(uint16 vct_status)
{
    if(vct_status == 0x0)
    {
        return MARS_PAIR_STATE_NORMAL;
    }
    else if(vct_status == 0x1)
    {
        return MARS_PAIR_STATE_ABNORMAL_TERMINATION;
    }
    else if(vct_status == 0x2)
    {
        return MARS_PAIR_STATE_ABNORMAL_SHORTED;
    }
    else if(vct_status == 0x3)
    {
        return MARS_PAIR_STATE_ABNORMAL_OPEN;
    }
    else
    {
        return MARS_PAIR_STATE_MAX;
    }
}

int32
ctc_phy_mars1s_get_vct_result(uint8 lchip, ctc_chip_mdio_para_t* param, void* result)
{
    mars_port_cable_info_t* p_cable_info;
    uint16 val = 0;
    uint16 A_status,B_status,C_status,D_status;

    p_cable_info = (mars_port_cable_info_t*)result;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x84, &val));
    PHY_DEBUG_PRINT("phy get port vct val:0x%x \n", val);
    if((val&0x8000)==0)
    {
        A_status = val & 0x3;
        B_status = (val>>2) & 0x3;
        C_status = (val>>4) & 0x3;
        D_status = (val>>6) & 0x3;
        p_cable_info->pair_A.pair_status = mars1s_vct_status_prase(A_status);
        p_cable_info->pair_B.pair_status = mars1s_vct_status_prase(B_status);
        p_cable_info->pair_C.pair_status = mars1s_vct_status_prase(C_status);
        p_cable_info->pair_D.pair_status = mars1s_vct_status_prase(D_status);

        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x87, &val));
        PHY_DEBUG_PRINT("phy get port vct pair_A val:0x%x \n", val);
        p_cable_info->pair_A.pair_length = (val/100) ? (val/100) : 1;;
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x88, &val));
        PHY_DEBUG_PRINT("phy get port vct pair_B val:0x%x \n", val);
        p_cable_info->pair_B.pair_length = (val/100) ? (val/100) : 1;
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x89, &val));
        PHY_DEBUG_PRINT("phy get port vct pair_C val:0x%x \n", val);
        p_cable_info->pair_C.pair_length = (val/100) ? (val/100) : 1;
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x8a, &val));
        PHY_DEBUG_PRINT("phy get port vct pair_D val:0x%x \n", val);
        p_cable_info->pair_D.pair_length = (val/100) ? (val/100) : 1;
    }
    else
    {
        return CTC_E_NOT_READY;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_lds_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    PHY_DEBUG_PRINT("phy set port lds enable:%d \n", enable);
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_LDS, 0x0, enable << 12,0x1000));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_LDS, 0x0, 0x8000,0x8000));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_lds_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val = 0;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_LDS, 0x0, &val));
    PHY_DEBUG_PRINT("phy get port lds en val:0x%x \n", val);
    *p_enable = (val >> 12) & 0x1;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_lds_details(uint8 lchip, ctc_chip_mdio_para_t* param, void* p_result)
{
    mars_lds_details_t* lds_details;
    uint16 val1 = 0;
    uint16 vala = 0;
    uint16 result = 0;

    lds_details = (mars_lds_details_t*)p_result;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_LDS, 0x1, &val1));
    PHY_DEBUG_PRINT("phy get port lds val1:0x%x \n", val1);
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_LDS, 0xa, &vala));
    PHY_DEBUG_PRINT("phy get port lds vala:0x%x \n", vala);

    lds_details->linkup= (val1 >> 2) & 0x1;
    lds_details->length= vala & 0xfff;
    PHY_MARS_ERROR_RETURN(mars1s_get_lds_result(lchip, param,&result));
    PHY_DEBUG_PRINT("phy get port lds result:0x%x \n", result);
    lds_details->result= result;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_link_status_details(uint8 lchip, ctc_chip_mdio_para_t* param, void* p_link_status)
{
    mars_link_status_t* link_status;

    link_status = (mars_link_status_t*)p_link_status;
    link_status->medium = 0;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_link_up_status(lchip,param,&link_status->link_up));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_port_speed(lchip,param,&link_status->speed_status));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_port_duplex(lchip,param,&link_status->duplex_status));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_port_auto_neg_en(lchip,param,&link_status->auto_neg_en));
    PHY_MARS_ERROR_RETURN(mars1s_get_page_link_status(lchip,param, MARS_PAGE_SGMII,&link_status->sg_link_up,&link_status->sg_speed_status));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_mdi_mdix_mode(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 mode)
{
    PHY_DEBUG_PRINT("phy set port mdi_mdix mode:%d \n", mode);
    if(mode == MARS_MANUAL_MDI)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, 0x10, 0x0, 0x0060));
    }
    else if(mode == MARS_MANUAL_MDIX)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, 0x10, 0x20, 0x0060));
    }
    else if(mode == MARS_MDI_MDIX_AUTO)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, 0x10, 0x60, 0x0060));
    }
    else
    {
        return ctc_phy_common_unsupport();
    }

    PHY_MARS_ERROR_RETURN(mars1s_do_soft_reset(lchip, param));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_mdi_mdix_mode(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_mode)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x10, &val));
    PHY_DEBUG_PRINT("phy get port mdi_mdix val:0x%x \n", val);
    if((val & 0x60) == 0x0)
    {
        *p_mode = MARS_MANUAL_MDI;
    }
    else if((val & 0x60) == 0x20)
    {
        *p_mode = MARS_MANUAL_MDIX;
    }
    else if((val & 0x60) == 0x60)
    {
        *p_mode = MARS_MDI_MDIX_AUTO;
    }
    else
    {
        return CTC_E_UNEXPECT;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_downgrade_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    PHY_DEBUG_PRINT("phy set port downgrade enable:%d \n", enable);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, 0x14, 0x0020, 0x0020));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip, param, MARS_PAGE_UTP, 0x14, 0x0000, 0x0020));
    }
    PHY_MARS_ERROR_RETURN(mars1s_do_soft_reset(lchip, param));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_downgrade_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x14, &val));
    PHY_DEBUG_PRINT("phy get port downgrade val:0x%x \n", val);
    if(val & 0x20)
    {
        *p_enable = GLB_ENABLE;
    }
    else
    {
        *p_enable = GLB_DISABLE;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_fast_link_down(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable, uint32 delay)
{
    PHY_DEBUG_PRINT("phy set port fast_link_down enable:%d, delay:%d\n", enable, delay);
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x34, 0x0000, 0x8000));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x37, (delay & 0x7) << 13, 0xe000));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x34, 0x8000, 0x8000));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_UTP, 0x37, (delay & 0x7) << 13, 0xe000));
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_fast_link_down(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable, uint32* p_delay)
{
    uint16 val;
    uint16 delay;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x34, &val));
    PHY_DEBUG_PRINT("phy get port fast_link_down val:0x%x \n", val);
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_UTP, 0x37, &delay));
    PHY_DEBUG_PRINT("phy get port fast_link_down delay val:0x%x \n", delay);
    if(val & 0x8000)
    {
        *p_enable = GLB_ENABLE;
    }
    else
    {
        *p_enable = GLB_DISABLE;
    }
    *p_delay = delay >> 13;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_led_blink(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 val)
{
    uint16 blink_val = 0;
    uint16 force_val = 0;
    uint16 reg = 0;

    if(val & MARS_LED_NUM_0)
    {
        reg = 0xa00c;
    }
    else if(val & MARS_LED_NUM_1)
    {
        reg = 0xa00d;
    }
    else if(val & MARS_LED_NUM_2)
    {
        reg = 0xa00e;
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    blink_val = val & MARS_LED_BLK_MASK;
    blink_val |= (val >> 21) & 0x3;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write(lchip, param, reg, blink_val));

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param, reg, &force_val));
    if(val & MARS_LED0_FORCE_EN)
        force_val |= 0x5;
    if(val & MARS_LED1_FORCE_EN)
        force_val |= 0x28;
    if(val & MARS_LED2_FORCE_EN)
        force_val |= 0x140;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write(lchip, param, 0xa00b, force_val));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_led_blink(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* val)
{
    uint32 result_val = 0;
    uint16 blink_val = 0;
    uint16 force_val = 0;
    uint16 reg = 0xb8;

    result_val = *val;
    if(result_val & MARS_LED_NUM_0)
    {
        reg = 0xa00c;
    }
    else if(result_val & MARS_LED_NUM_1)
    {
        reg = 0xa00d;
    }
    else if(result_val & MARS_LED_NUM_2)
    {
        reg = 0xa00e;
    }
    else
    {
        return CTC_E_INVALID_PARAM;
    }

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param, reg, &blink_val));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param, 0xa00b, &force_val));

    result_val |= (blink_val & 0x3fff);

    if((force_val & 0xc000) == 0x0)
        result_val |= MARS_LED_SRC_SEL_UTP;
    if((force_val & 0xc000) == 0x4000)
        result_val |= MARS_LED_SRC_SEL_SERDES;
    if((force_val & 0xc000) == 0x8000)
        result_val |= MARS_LED_SRC_SEL_UTP_AND_SERDES;
    if((force_val & 0xc000) == 0xc000)
        result_val |= MARS_LED_SRC_SEL_UTP_OR_SERDES;

    if(force_val & 0x5)
        result_val |= MARS_LED0_FORCE_EN;
    if(force_val & 0x28)
        result_val |= MARS_LED1_FORCE_EN;
    if(force_val & 0x140)
        result_val |= MARS_LED2_FORCE_EN;

    *val = result_val;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_jumbo_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable)
{
    if(enable)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write_mask(lchip, param, 0xa006, 0x0080, 0x0080));
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write_mask(lchip, param, 0xa006, 0x0000, 0x0080));
    }
    PHY_MARS_ERROR_RETURN(mars1s_do_soft_reset(lchip, param));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_jumbo_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param, 0xa006, &val));
    if(val & 0x80)
    {
        *p_enable= GLB_ENABLE;
    }
    else
    {
        *p_enable= GLB_DISABLE;
    }

    return CTC_E_NONE;
}

static int32
mars1s_set_synce(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable, uint32 freq,uint16* value)
{
    uint16 val = 0;

    val = *value;
    if(enable)
    {
        val |= 0x20;    /* enable synce */

        val |= 0x2;    /* select copper */
        val &= 0xfffb;

        if(freq == MARS_SYNCE_FREQ_25MHZ)
        {
            val &= 0xfff7;
        }
        else if(freq == MARS_SYNCE_FREQ_125MHZ)
        {
            val |= 0x8;
        }
        else if(freq == MARS_LOCAL_FREQ_25MHZ)
        {
            val &= 0xfff1;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_sleep_mode_en(lchip, param, GLB_DISABLE));
        }
        else
        {
            return ctc_phy_common_unsupport();
        }
    }
    else
    {
        val &= 0xffdf;
    }
    *value = val;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_synce_en(uint8 lchip, ctc_chip_mdio_para_t* param, void* pv_arg)
{
    uint16 val = 0;
    mars_synce_t* synce;

    synce = (mars_synce_t*)pv_arg;

    PHY_MARS_ERROR_RETURN(mars1s_set_synce(lchip,param,synce->enable,synce->freq,&val));
    PHY_DEBUG_PRINT("phy set port synce_en val:0x%x \n", val);

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write(lchip, param,0xa012,val));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_synce_en(uint8 lchip, ctc_chip_mdio_para_t* param, void* pv_arg)
{
    mars_synce_t* synce;
    uint16 val = 0;

    synce = (mars_synce_t*)pv_arg;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip, param,0xa012,&val));
    PHY_DEBUG_PRINT("phy get port synce_en val:0x%x \n", val);

    if(val & 0x20)
    {
        synce->enable = GLB_ENABLE;
    }
    else
    {
        synce->enable = GLB_DISABLE;
    }

    if(val & 0x8)
    {
        synce->freq = MARS_SYNCE_FREQ_125MHZ;
    }
    else
    {
        synce->freq = MARS_SYNCE_FREQ_25MHZ;
    }

    return CTC_E_NONE;
}

static uint32
mars1s_get_prbs_type(uint16 val)
{
    if((val & 0x1e0) == 0x0)
    {
        return MARS_TEST_MODE_PRBS7;
    }
    else if((val & 0x1e0) == 0x20)
    {
        return MARS_TEST_MODE_PRBS10;
    }
    else if((val & 0x1e0) == 0x100)
    {
        return MARS_TEST_MODE_PRBS31;
    }
    else
    {
        return MARS_TEST_MODE_MAX;
    }
}

int32
ctc_phy_mars1s_set_prbs_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable, uint32 prbs)
{
    if(enable)
    {
        if(prbs == MARS_TEST_MODE_PRBS7)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x8000, 0x81e0));
        }
        else if(prbs == MARS_TEST_MODE_PRBS10)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x8020, 0x81e0));
        }
        else if(prbs == MARS_TEST_MODE_PRBS31)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x8100, 0x81e0));
        }
        else
        {
            return ctc_phy_common_unsupport();
        }
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x0000, 0x8000));
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_prbs_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable, uint32* p_prbs)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_SGMII,0x5,&val));

    *p_enable = (val & 0x8000) ? GLB_ENABLE : GLB_DISABLE;
    *p_prbs = mars1s_get_prbs_type(val);

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_prbs_check_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 enable, uint32 prbs)
{
    if(enable)
    {
        if(prbs == MARS_TEST_MODE_PRBS7)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x4000, 0x41e0));
        }
        else if(prbs == MARS_TEST_MODE_PRBS10)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x4020, 0x41e0));
        }
        else if(prbs == MARS_TEST_MODE_PRBS31)
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x4100, 0x41e0));
        }
        else
        {
            return ctc_phy_common_unsupport();
        }
    }
    else
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write_mask(lchip, param, MARS_PAGE_SGMII, 0x5, 0x0000, 0x4000));
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_prbs_check_en(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_enable, uint32* p_prbs)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_SGMII,0x5,&val));

    *p_enable = (val & 0x4000) ? GLB_ENABLE : GLB_DISABLE;
    *p_prbs = mars1s_get_prbs_type(val);

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_prbs_result(uint8 lchip, ctc_chip_mdio_para_t* param, void* pv_arg)
{
    uint16 val,error_high,error_low;
    mars_prbs_result_t* prbs_result;

    prbs_result = (mars_prbs_result_t*)pv_arg;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip, param, MARS_PAGE_SGMII,0x5,&val));
    prbs_result->prbs= mars1s_get_prbs_type(val);

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param, MARS_PAGE_SGMII,0x8,&val));
    prbs_result->sync= (val & 0x1) ? MARS_SYNC: MARS_OUT_SYNC;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param, MARS_PAGE_SGMII,0x9,&error_low));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param, MARS_PAGE_SGMII,0xa,&error_high));
    prbs_result->error= (error_high << 16) | error_low;

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_test_mode(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 mode, uint32 speed)
{
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_sleep_mode_en(lchip, param, GLB_DISABLE));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x10, 0x0002));

    if (speed == GLB_SPEED_1G)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x8140, 0xb140)); /* force speed */
    }
    else if (speed == GLB_SPEED_100M)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0xa100, 0xb140)); /* force speed */
    }
    else if (speed == GLB_SPEED_10M)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, PHY_CTL_REG, 0x8100, 0xb140)); /* force speed */
    }

    if(mode == MARS_TEST_MODE_DISABLE)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x9, 0x0600));
        PHY_MARS_ERROR_RETURN(mars1s_config_recover(lchip,param));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x10, 0x0062));
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_sleep_mode_en(lchip, param, GLB_ENABLE));
    }
    else if(mode == MARS_TEST_MODE_1)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x9, 0x2200));
    }
    else if(mode == MARS_TEST_MODE_2)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x9, 0x5a00));
    }
    else if(mode == MARS_TEST_MODE_3)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x9, 0x7200));
    }
    else if(mode == MARS_TEST_MODE_4)
    {
        PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip, param, MARS_PAGE_UTP, 0x9, 0x8200));
    }
    else
    {
        return ctc_phy_common_unsupport();
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_master_slave(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 mode)
{
    switch (mode)
    {
        case GLB_MODE_AUTO:
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x9, 0x0000, 0x1000));
            break;
        case GLB_MODE_MASTER:
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x9, 0x1800, 0x1800));
            break;
        case GLB_MODE_SLAVE:
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write_mask(lchip,param, MARS_PAGE_UTP, 0x9, 0x1000, 0x1800));
            break;
        default:
            return RESULT_ERROR;
            break;
    }

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_get_master_slave(uint8 lchip, ctc_chip_mdio_para_t* param, uint32* p_mode)
{
    uint16 val;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x9, &val));
    if(val & 0x1000)
    {
        *p_mode= (val & 0x0800) ? GLB_MODE_MASTER : GLB_MODE_SLAVE;
    }
    else
    {
        *p_mode= GLB_MODE_AUTO;
    }

    return CTC_E_NONE;
}

uint32
ctc_phy_mars1s_warmboot_sync(uint8 lchip, ctc_chip_mdio_para_t* param)
{
    uint32 enable = 0;
    uint16 val,val0;
    uint8 port_id;

    port_id = ctc_phy_common_get_port_id(g_phy_port_info,param);
    ctc_phy_common_probe_id(lchip,param,&g_phy_port_info[port_id].phy_id);
    g_phy_port_info[port_id].lchip = lchip;/* init */
    g_phy_port_info[port_id].bus = param->bus;
    g_phy_port_info[port_id].phy_addr = param->phy_addr;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_port_en(lchip, param, &enable));
    PHY_DEBUG_PRINT("enable cfg:0x%x \n", g_phy_port_info[port_id].enable);
    g_phy_port_info[port_id].enable = enable;
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_port_auto_neg_en(lchip, param, &enable));
    PHY_DEBUG_PRINT("auto enable cfg:0x%x \n", enable);
    g_phy_port_info[port_id].auto_neg_en = enable;
    PHY_MARS_ERROR_RETURN(mars1s_port_status_sync(lchip, param, enable));

    g_phy_port_info[port_id].mdium = GLB_PORT_TYPE_COPPER;
    g_phy_port_info[port_id].mac_if = GLB_MAC_INTERFACE_SGMII;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0x0, &val0));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip, param, MARS_PAGE_UTP, 0xa, &val));
    PHY_DEBUG_PRINT("phy get port loopback value0:0x%x valuea:0x%x \n", val0, val);
    if(val0 & 0x4000)
    {
        PHY_DEBUG_PRINT("GLB_LB_PHY_NEAR \n");
        g_phy_port_info[port_id].loopback_mode= GLB_LB_PHY_NEAR;
    }
    else if(val & 0x20)
    {
        PHY_DEBUG_PRINT("GLB_LB_PHY_FAR \n");
        g_phy_port_info[port_id].loopback_mode= GLB_LB_PHY_FAR;
    }
    else
    {
        PHY_DEBUG_PRINT("GLB_LB_NONE \n");
        g_phy_port_info[port_id].loopback_mode= GLB_LB_NONE;
    }
    g_phy_port_info[port_id].undir_en = 0;

    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_speed_force(lchip, param, &g_phy_port_info[port_id].speed_force));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_duplex_force(lchip, param, &g_phy_port_info[port_id].duplex_force));
    PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_speed_ability(lchip, param, &g_phy_port_info[port_id].speed_ability));

    return CTC_E_NONE;
}

int32
ctc_phy_mars1s_set_ext_attr(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 type, void* p_value)
{
    type -= CTC_PORT_PROP_PHY_CUSTOM_BASE;
    switch (type)
    {
        case PHY_SET_PKT_CK:
        {
            packet_checker_t* pktck;
            uint32 enable;
            uint32 stream;

            pktck = (packet_checker_t*)p_value;
            enable = pktck->enable;
            stream = pktck->stream;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_packet_checker(lchip,param,enable,stream));
            return CTC_E_NONE;
        }
        case PHY_SET_PKT_GEN:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_packet_gen(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_SET_PKT_GEN_EN:
        {
            uint32 enable;

            enable = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_packet_gen_en(lchip,param,enable));
            return CTC_E_NONE;
        }
        case PHY_SET_VCT_EN:
        {
            uint32 enable;

            enable = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_vct_en(lchip,param,enable));
            return CTC_E_NONE;
        }
        case PHY_SET_MDIMDIX_MODE:
        {
            uint32 mode;

            mode = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_mdi_mdix_mode(lchip,param,mode));
            return CTC_E_NONE;
        }
        case PHY_SET_DOWNGRADE_EN:
        {
            uint32 enable;

            enable = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_downgrade_en(lchip,param,enable));
            return CTC_E_NONE;
        }
        case PHY_SET_FASTLINKDOWN:
        {
            fast_link_down_t* fast_link_down;
            uint32 enable;
            uint32 delay;

            fast_link_down = (fast_link_down_t*)p_value;
            enable = fast_link_down->enable;
            delay = fast_link_down->delay;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_fast_link_down(lchip,param,enable,delay));
            return CTC_E_NONE;
        }
        case PHY_SET_LDS_EN:
        {
            uint32 enable;

            enable = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_lds_en(lchip,param,enable));
            return CTC_E_NONE;
        }
        case PHY_SET_LED_BLINK:
        {
            uint32 val;

            val = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_led_blink(lchip,param,val));
            return CTC_E_NONE;
        }
        case PHY_SET_JUMBO:
        {
            uint32 enable;

            enable = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_jumbo_en(lchip,param,enable));
            return CTC_E_NONE;
        }
        case PHY_SET_SYNCE:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_synce_en(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_SET_PRBS:
        {
            prbs_en_t* prbs_en;
            uint32 enable;
            uint32 prbs;

            prbs_en = (prbs_en_t*)p_value;
            enable = prbs_en->enable;
            prbs = prbs_en->prbs;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_prbs_en(lchip,param,enable,prbs));
            return CTC_E_NONE;
        }
        case PHY_SET_PRBS_CK:
        {
            prbs_en_t* prbs_en;
            uint32 enable;
            uint32 prbs;

            prbs_en = (prbs_en_t*)p_value;
            enable = prbs_en->enable;
            prbs = prbs_en->prbs;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_prbs_check_en(lchip,param,enable,prbs));
            return CTC_E_NONE;
        }
        case PHY_SET_TESTMODE:
        {
            test_mode_t* test;

            test = (test_mode_t*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_test_mode(lchip,param,test->mode,test->speed));
            return CTC_E_NONE;
        }
        case PHY_EXT_WRITE:
        {
            phy_ext_t* phy_ext;
            uint32 reg;
            uint32 value;

            phy_ext = (phy_ext_t*)p_value;
            reg = phy_ext->reg;
            value = phy_ext->value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_write(lchip,param,reg,value));
            return CTC_E_NONE;
        }
        case PHY_PAGE_WRITE:
        {
            phy_page_ext_t* phy_ext;
            uint32 reg;
            uint32 value;
            uint32 page;

            phy_ext = (phy_page_ext_t*)p_value;
            reg = phy_ext->reg;
            value = phy_ext->value;
            page = phy_ext->page;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_write(lchip,param,page,reg,value));
            return CTC_E_NONE;
        }
        case PHY_PAGE_EXT_WRITE:
        {
            phy_page_ext_t* phy_ext;
            uint32 reg;
            uint32 value;
            uint32 page;

            phy_ext = (phy_page_ext_t*)p_value;
            reg = phy_ext->reg;
            value = phy_ext->value;
            page = phy_ext->page;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_write(lchip,param,page,reg,value));
            return CTC_E_NONE;
        }
        case PHY_SET_SLEEP_EN:
        {
            uint32 enable;

            enable = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_sleep_mode_en(lchip,param,enable));
            return CTC_E_NONE;
        }
        case PHY_SET_EEE_EN:
        {
            uint32 enable;

            enable = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_eee_en(lchip,param,enable));
            return CTC_E_NONE;
        }
        case PHY_SET_SPEED_FORCE:
        {
            uint8 speed;

            speed = *(uint8*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_phy_speed_force(lchip,param,speed));
            return CTC_E_NONE;
        }
         case PHY_SET_DUPLEX_FORCE:
        {
            uint8 duplex;

            duplex = *(uint8*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_phy_duplex_force(lchip,param,duplex));
            return CTC_E_NONE;
        }
        case PHY_SET_SPEED_ABILITY:
        {
            uint8 ability;

            ability = *(uint8*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_phy_speed_ability(lchip,param,ability));
            return CTC_E_NONE;
        }
       case PHY_WARMBOOT_SYNC:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_warmboot_sync(lchip,param));
            return CTC_E_NONE;
        }
        case PHY_SET_MASTER_SLAVE:
        {
            uint32 mode;

            mode = *(uint32*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_set_master_slave(lchip,param,mode));
            return CTC_E_NONE;
        }
        default:
            return CTC_E_NOT_SUPPORT;
    }
}

int32
ctc_phy_mars1s_get_ext_attr(uint8 lchip, ctc_chip_mdio_para_t* param, uint32 type, void* p_value)
{
    type -= CTC_PORT_PROP_PHY_CUSTOM_BASE;
    switch (type)
    {
        case PHY_GET_PKT_CK:
        {
            packet_checker_t* pktck;
            pktck = (packet_checker_t*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_packet_checker(lchip,param,&pktck->enable,&pktck->stream));
            return CTC_E_NONE;
        }
        case PHY_GET_PKT_COUNT:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_packet_count(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_PKT_GEN:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_packet_gen(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_PKT_GEN_EN:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_packet_gen_en(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_VCT_RESULT:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_vct_result(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_LINK_STATUS_DETAILS:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_link_status_details(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_MDIMDIX_MODE:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_mdi_mdix_mode(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_DOWNGRADE_EN:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_downgrade_en(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_FASTLINKDOWN:
        {
            fast_link_down_t* fastld;
            fastld = (fast_link_down_t*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_fast_link_down(lchip,param,&fastld->enable,&fastld->delay));
            return CTC_E_NONE;
        }
        case PHY_GET_LDS_EN:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_lds_en(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_LDS_RESULT:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_lds_details(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_LED_BLINK:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_led_blink(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_JUMBO:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_jumbo_en(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_SYNCE:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_synce_en(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_PRBS:
        {
            prbs_en_t* prbsen;
            prbsen = (prbs_en_t*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_prbs_en(lchip,param,&prbsen->enable,&prbsen->prbs));
            return CTC_E_NONE;
        }
        case PHY_GET_PRBS_CK:
        {
            prbs_en_t* prbsck;
            prbsck = (prbs_en_t*)p_value;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_prbs_check_en(lchip,param,&prbsck->enable,&prbsck->prbs));
            return CTC_E_NONE;
        }
        case PHY_GET_PRBS_RESULT:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_prbs_result(lchip,param,p_value));
            return CTC_E_NONE;
        }
        case PHY_EXT_READ:
        {
            uint32 reg;
            phy_ext_t* phy_ext;
            phy_ext = (phy_ext_t*)p_value;
            reg = phy_ext->reg;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_ext_read(lchip,param,reg,&phy_ext->value));
            return CTC_E_NONE;
        }
        case PHY_PAGE_READ:
        {
            uint32 reg;
            uint32 page;
            phy_page_ext_t* phy_ext;
            phy_ext = (phy_page_ext_t*)p_value;
            page = phy_ext->page;
            reg = phy_ext->reg;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_read(lchip,param,page,reg,&phy_ext->value));
            return CTC_E_NONE;
        }
        case PHY_PAGE_EXT_READ:
        {
            uint32 reg;
            uint32 page;
            phy_page_ext_t* phy_ext;
            phy_ext = (phy_page_ext_t*)p_value;
            page = phy_ext->page;
            reg = phy_ext->reg;
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_page_ext_read(lchip,param,page,reg,&phy_ext->value));
            return CTC_E_NONE;
        }
        case PHY_GET_SLEEP_EN:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_sleep_mode_en(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_EEE_EN:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_eee_en(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_EEE_STATUS:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_eee_status(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_SPEED_FORCE:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_speed_force(lchip,param,(uint8*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_DUPLEX_FORCE:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_duplex_force(lchip,param,(uint8*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_SPEED_ABILITY:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_phy_speed_ability(lchip,param,(uint8*)p_value));
            return CTC_E_NONE;
        }
        case PHY_GET_MASTER_SLAVE:
        {
            PHY_MARS_ERROR_RETURN(ctc_phy_mars1s_get_master_slave(lchip,param,(uint32*)p_value));
            return CTC_E_NONE;
        }
        default:
            return CTC_E_NOT_SUPPORT;
    }
}

/**
@ingroup DRVTBL
@details This is the driver for mars1s.
*/
ctc_phy_driver_t ctc_chip_phy_mars1s_api =
{
    .init = ctc_phy_mars1s_init,
    .deinit = ctc_phy_mars1s_deinit,
    .set_port_en = ctc_phy_mars1s_set_port_en,
    .get_port_en = ctc_phy_mars1s_get_port_en,
    .set_port_duplex_en = ctc_phy_mars1s_set_port_duplex,
    .get_port_duplex_en = ctc_phy_mars1s_get_port_duplex,
    .set_port_speed = ctc_phy_mars1s_set_port_speed,
    .get_port_speed = ctc_phy_mars1s_get_port_speed,
    .set_port_auto_neg_en = ctc_phy_mars1s_set_port_auto_neg_en,
    .get_port_auto_neg_en = ctc_phy_mars1s_get_port_auto_neg_en,
    .set_port_loopback = ctc_phy_mars1s_set_port_loopback,
    .get_port_loopback = ctc_phy_mars1s_get_port_loopback,
    .get_link_up_status = ctc_phy_mars1s_get_link_up_status,
    .linkup_event = ctc_phy_mars1s_linkup_event,
    .linkdown_event = ctc_phy_mars1s_linkdown_event,
    .set_port_unidir_en = ctc_phy_mars1s_set_port_unidir_en,
    .get_port_unidir_en =ctc_phy_mars1s_get_port_unidir_en,
    .set_port_medium = ctc_phy_mars1s_set_port_medium,
    .get_port_medium = ctc_phy_mars1s_get_port_medium,
    .set_ext_attr = ctc_phy_mars1s_set_ext_attr,
    .get_ext_attr = ctc_phy_mars1s_get_ext_attr,
};

/**
@fn int32 ctc_phy_driver_get_mars1s(void *drv)
@details This function will be called in ctc_app_phy_init for register driver for mars1s.
@return the driver interface about mars1s.
*/
int32
ctc_phy_driver_get_mars1s(void **drv)
{
    *drv = (void*)(&ctc_chip_phy_mars1s_api);
    return 0;
}

#ifdef CTC_PHY_DRV_PLUGIN
extern uint8 g_ctcs_api_en;

int32
ctc_app_phy_mars1s_init(uint8 lchip, uint32 phy_id, uint32 phy_id_mask, char* phy_name)
{
    ctc_chip_phy_shim_t phy_shim;

    sal_memset(&phy_shim, 0, sizeof(ctc_chip_phy_shim_t));
    phy_shim.phy_id = phy_id;
    phy_shim.phy_id_mask = phy_id_mask;
    sal_memcpy(phy_shim.phy_name, phy_name, CTC_CHIP_PHY_NAME_MAX_LEN);
    sal_memcpy(&phy_shim.driver, &ctc_chip_phy_mars1s_api, sizeof(ctc_phy_driver_t));
    phy_shim.event_mode = CTC_CHIP_PHY_SHIM_EVENT_MODE_POLLING;
    phy_shim.poll_interval = GLB_PHY_POLLING_INTERVAL;/* ms */
    if (g_ctcs_api_en)
    {
        ctcs_chip_set_property(lchip, CTC_CHIP_PROP_REGISTER_PHY, (void*)&phy_shim);
    }
    else
    {
        ctc_chip_set_property(lchip, CTC_CHIP_PROP_REGISTER_PHY, (void*)&phy_shim);
    }

    return CTC_E_NONE;
}

void
ctc_app_phy_driver_init(uint8 lchip)
{
    ctc_app_phy_mars1s_init(lchip, PHY_TYPE_MARS1S, 0xfffffff0, "mars1s");
    ctc_app_phy_mars1s_init(lchip, PHY_TYPE_MARS1S_V1, 0xfffffff0, "mars1s_v1");

    return;
}
#endif
#endif

